#include "data.h"
#include "ui_data.h"
#include "constants.h"
#include <QDebug>
#include <QTableWidgetItem>
#include <QScrollBar>
#include <QListView>
#include <QFileDialog>
#include <QPrintDialog>
#include <QTextDocument>
//#include <QtDBus/QDBusConnection>
#include <QMessageBox>
#include "shadow.h"
#include "msgbox.h"
#include "log4z.h"
#include "authmanager.h"
#include "udiskexport.h"
#include "loading.h"
#include "materialchecker.h"
#include "userlogger.h"
#include "chartutils.h"
#include "customprinter.h"
#include "translation.h"

using namespace zsummer::log4z;

static const QStringList result = QStringList() << QObject::tr("Pass") << QObject::tr("Fail");

Data::Data(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Data)
{
    ui->setupUi(this);
    bdf = BllDataFlow::getInstance();
    sqlHelper = SqlHelper::getInstance();
    exportMgr = new UdiskExport(this);

    //Signals and Slots
    connect(bdf, &BllDataFlow::setWidgetVisibleSignal, this, &Data::setWidgetVisibleSlot);
    connect(bdf, &BllDataFlow::showAllParametersSignal, this, &Data::showAllParameters);
    connect(bdf, &BllDataFlow::retranslateUiSignal, this, &Data::retranslateUiSlot);
    connect(bdf, &BllDataFlow::selectDateTimePickerSignal, this, &Data::changeDateTime);
    connect(bdf, &BllDataFlow::generateAllHtmlSucceedSignal, this, &Data::setReportHtml);
    connect(bdf, &BllDataFlow::setCurrentTimeSignal, this, &Data::setCurrentTimeSlot);
    connect(exportMgr, &UdiskExport::done, this, &Data::pdfSaveDone);

    dateTimePicker = new DateTimePicker(nullptr, DateTimeType::Date | DateTimeType::Hour | DateTimeType::Minute);

    initWidget();
}

Data::~Data()
{
    delete ui;
}

void Data::save(const QString &path)
{
    MyOffice().savePdf(path, contentHtml);
}

void Data::showEvent(QShowEvent *)
{
    this->activateWindow();
}

void Data::on_btnQuery_clicked()
{
    ui->btnQuery->setEnabled(false);

    QString startDateTime = ui->dateTimeEditStart->dateTime().toString(FMT_S);
    QString endDateTime = ui->dateTimeEditEnd->dateTime().toString(FMT_S);
    QString parameterName = ui->cbxParamName->currentText();
    QString sampleISN = ui->lineSampleISN->text();
    QString materialBatchNo = ui->lineMaterialBatchNo->text();
    QString materialSpec = ui->cbxMaterialType->currentText();
    QString result = ui->cbxResult->currentText();
    if (!result.isEmpty())
    {
        result = ui->cbxResult->currentIndex() == 1 ? EXP_PASS : EXP_FAIL;
    }

    QString username = currentUsername;

    if (hasViewAllDataPermission())
    {// 角色有查看所有用户的权限
        if (AuthManager::instance()->isManufacturer(currentUsername))
        {// 厂家账号，可以查看所有数据
            username = "";
        }
        else
        {// 非厂家账号，过滤掉厂家数据
            username = "!=" + AuthManager::instance()->manufacturer();
        }
    }

    expList = sqlHelper->selectExperiment(startDateTime, endDateTime, username, parameterName, result, sampleISN, materialBatchNo, materialSpec);
    int count = expList.size();
    UserLogger::log(QString("%1%2~%3%4\n>%5: %6").arg(tr("Query")).arg(startDateTime).arg(endDateTime).arg(tr("Experiment record")).arg(tr("Records Count")).arg(count));

    if (count > 0)
    {
        contentHtml.clear();
        contentHtml += generateTable(tableHeader, expList);
        bdf->generateAllHtml(ReportType::DATA_REPROT, contentHtml);
        ui->btnPrint->setEnabled(true);
        ui->btnExport->setEnabled(true);
    }
    else
    {
        contentHtml.clear();
        reportHtml.clear();
        ui->btnPrint->setEnabled(false);
        ui->btnExport->setEnabled(false);
    }

    showExperimentInfo(expList);
    ui->btnQuery->setEnabled(true);
}

void Data::on_btnPrint_clicked()
{
    ShowPrintDialog(contentHtml, tr("Print Experiment record"));
}

void Data::on_btnExport_clicked()
{
    Loading::showLoading(QColor(0,0,0,200), false, tr("exporting..."));
    UserLogger::log(tr("Export Experiment record"));
    exportMgr->exports(ReportType::DATA_REPROT, this);
    ui->btnExport->setEnabled(false);
}

void Data::setWidgetVisibleSlot(int permission)
{
    AuthManager::instance()->showControls(ui->widget_8, permission);
    ui->tableWidget->setRowCount(0);
    ui->btnPrint->setEnabled(false);
    ui->btnExport->setEnabled(false);
    resizeTableColumnWidth();
}

void Data::showAllParameters()
{        
    ui->cbxParamName->clear();
    ui->cbxParamName->addItem("");
    ui->cbxParamName->setCurrentIndex(0);

    QList<QStringList> paramList = sqlHelper->selectAllFromTable("t_parameter");
    for (int i = 0;i < paramList.size();i++)
    {
        ui->cbxParamName->addItem(paramList[i].at(ParameterIndex::PARAM_NAME));
    }
}

void Data::showAllMaterialType()
{
    ui->cbxMaterialType->clear();
    ui->cbxMaterialType->addItem("");
    ui->cbxMaterialType->setCurrentIndex(0);
    ui->cbxMaterialType->addItems(MaterialChecker::getMaterialTypeList());
}

void Data::showAllResultType()
{
    int currentIndex = ui->cbxResult->currentIndex();
    ui->cbxResult->clear();
    ui->cbxResult->addItem("");
    ui->cbxResult->addItem(Tr(EXP_PASS));
    ui->cbxResult->addItem(Tr(EXP_FAIL));
    ui->cbxResult->setCurrentIndex(currentIndex);
}

void Data::initWidget()
{
    initTableHeader();
    resizeTableColumnWidth();
    setShadow({ui->widget_5,ui->widget_6,ui->cbxParamName,ui->cbxResult,ui->lineSampleISN,ui->cbxMaterialType,ui->lineMaterialBatchNo});
    //设置强焦点策略,这样输入法面板隐藏以后单击界面不会弹出
//    this->setFocusPolicy(Qt::StrongFocus);

    //不需要虚拟键盘
    ui->tableWidget->setProperty("noinput", true);
    ui->dateTimeEditStart->setProperty("noinput", true);
    ui->dateTimeEditEnd->setProperty("noinput", true);
    ui->cbxMaterialType->setProperty("noinput", true);
    ui->cbxParamName->setProperty("noinput", true);
    ui->cbxResult->setProperty("noinput", true);

    //修改Combobox样式
    ui->cbxMaterialType->setView(new QListView());
    ui->cbxResult->setView(new QListView());
    ui->cbxParamName->setView(new QListView());
    ui->cbxParamName->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    ui->cbxMaterialType->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    int headerHeight = 50;
    ui->tableWidget->horizontalHeader()->setFixedHeight(headerHeight);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);//最后一个单元格扩展
    ui->tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
    ui->tableWidget->verticalHeader()->hide();
    ui->tableWidget->verticalScrollBar()->setStyleSheet("QScrollBar::vertical {width: 40px;}");

    showAllParameters();
    showAllMaterialType();
    showAllResultType();
}

void Data::resizeTableColumnWidth()
{
    if (windowWidth >= 1280)
    {
        this->setProperty("cssSize", "large");
        ui->widget_5->setFixedWidth(250);
        ui->btnDateTimeEditStart->setFixedWidth(250);
        ui->dateTimeEditStart->setFixedWidth(250);
        ui->widget_6->setFixedWidth(250);
        ui->btnDateTimeEditEnd->setFixedWidth(250);
        ui->dateTimeEditEnd->setFixedWidth(250);

        int w = ui->tableWidget->isColumnHidden(1) ? 10 : 0;

        ui->tableWidget->setColumnWidth(0, w + 230); //实验时间
        ui->tableWidget->setColumnWidth(1, w + 90);  //操作人
        ui->tableWidget->setColumnWidth(2, w + 100); //参数名称
        ui->tableWidget->setColumnWidth(3, w + 120); //样本条码
        ui->tableWidget->setColumnWidth(4, w + 85); //耗材规格
        ui->tableWidget->setColumnWidth(5, w + 110); //耗材批号
        ui->tableWidget->setColumnWidth(6, w + 90); //有效值
        ui->tableWidget->setColumnWidth(7, w + 85); //偏差值
        ui->tableWidget->setColumnWidth(8, w + 80); //报告单
        ui->tableWidget->setColumnWidth(9, w + 100); //运行时长
        ui->tableWidget->setColumnWidth(10, w + 60); //实验结果
    }
    else
    {
        int w = ui->tableWidget->isColumnHidden(1) ? 7 : 0;

        ui->tableWidget->setColumnWidth(0, w + 120); //实验时间
        ui->tableWidget->setColumnWidth(1, w + 70);  //操作人
        ui->tableWidget->setColumnWidth(2, w + 80);  //参数名称
        ui->tableWidget->setColumnWidth(3, w + 75);  //样本条码
        ui->tableWidget->setColumnWidth(4, w + 70);  //耗材规格
        ui->tableWidget->setColumnWidth(5, w + 80);  //耗材批号
        ui->tableWidget->setColumnWidth(6, w + 80);  //有效值
        ui->tableWidget->setColumnWidth(7, w + 80);  //偏差值
        ui->tableWidget->setColumnWidth(8, w + 80);  //报告单
        ui->tableWidget->setColumnWidth(9, w + 80);  //运行时长
        ui->tableWidget->setColumnWidth(10, w + 80); //实验结果
    }
}

void Data::retranslateTable()
{
    initTableHeader();
}

bool Data::hasViewAllDataPermission()
{
    User user = {};
    user.name = currentUsername;
    int permission = SqlHelper::getInstance()->selectUserPermission(user);
    return AuthManager::instance()->hasPermission(permission, AllData);
}

void Data::dataCalc(const ExperimentInfo &data, QString &vrmsStr, QString &offsetStr)
{
    if (data.result != EXP_PASS)
    {
        vrmsStr = offsetStr = "-";
        return;
    }

    double sum = 0;
    QList<QPointF> points;
    ChartUtils::readChartData(data.voltageRmsDatapath, points);
    for (int i = points.length() - 1; i >= 0; i--)
    {
        sum += points.at(i).y();
    }

    double vrms = (points.length() > 0) ? sum / points.length() : 0;
    double offset = (data.voltage != 0) ? (vrms - data.voltage) / data.voltage : 1;

    vrmsStr = doubleToString(vrms, 2);
    offsetStr = doubleToString(offset * 100, 2);
}

QString Data::translate(const QString &result)
{
    return (result == EXP_PASS) ? Tr(EXP_PASS) : Tr(EXP_FAIL);
}

void Data::showExperimentInfo(QList<ExperimentInfo> expList)
{
    int count = expList.size();
    ui->tableWidget->clearContents();
    if (count == 0) {
        ui->tableWidget->setRowCount(1);
        ui->tableWidget->setRowHeight(0, windowWidth >= 1280 ? 300 : 220);
        ui->tableWidget->setSpan(0,0,1,11);
        QTableWidgetItem * item = new QTableWidgetItem(tr("No data yet"));
        item->setTextAlignment(Qt::AlignCenter);
        ui->tableWidget->setItem(0,0,item);
        ui->tableWidget->setShowGrid(false);
        return;
    } else {
        ui->tableWidget->setSpan(0,0,1,1);
        ui->tableWidget->setShowGrid(true);
    }

    QString vrmsStr, offsetStr;
    ui->tableWidget->setRowCount(count);
    for (int r = 0; r < count; r++) {
        dataCalc(expList[r], vrmsStr, offsetStr);

        ui->tableWidget->setItem(r,0,new QTableWidgetItem(expList[r].datetimeExpStart));
        ui->tableWidget->setItem(r,1,new QTableWidgetItem(expList[r].username));
        ui->tableWidget->setItem(r,2,new QTableWidgetItem(expList[r].parameterName));
        ui->tableWidget->setItem(r,3,new QTableWidgetItem(expList[r].sampleName));
        ui->tableWidget->setItem(r,4,new QTableWidgetItem(expList[r].specifications));
        ui->tableWidget->setItem(r,5,new QTableWidgetItem(expList[r].batchNumber));
        ui->tableWidget->setItem(r,6,new QTableWidgetItem(vrmsStr));
        ui->tableWidget->setItem(r,7,new QTableWidgetItem(offsetStr));
        ui->tableWidget->setItem(r,9,new QTableWidgetItem(expList[r].duration));
        ui->tableWidget->setItem(r,10,new QTableWidgetItem(translate(expList[r].result)));

        QWidget * widget = new QWidget(this);
        QHBoxLayout * layout = new QHBoxLayout(this);
        QPushButton * btnViewReport = new QPushButton(this);
        layout->setMargin(5);
        layout->addWidget(btnViewReport);
        widget->setLayout(layout);
        ui->tableWidget->setCellWidget(r,8,widget);
        btnViewReport->setStyleSheet("border-image:url(:/resources/data_chart.png);color:#1e2b58;font-size:18px");
        if (windowWidth >= 1280) {
            btnViewReport->setGeometry(0,0,84,48);
        } else {
            btnViewReport->setGeometry(0,0,70,40);
        }

        btnViewReport->setText(tr("View"));
        btnViewReport->setWhatsThis(QString::number(r));
        connect(btnViewReport, &QPushButton::clicked, this, &Data::viewReportSlot);

        int rowHeight = 50;
        ui->tableWidget->setRowHeight(r, rowHeight);
        for (int j = 0; j < ui->tableWidget->columnCount(); j++)
        {
            if (j != 8)
            {
                ui->tableWidget->item(r, j)->setTextAlignment(Qt::AlignCenter);
            }
        }
    }
}

void Data::initTableHeader()
{
    tableHeader.clear();
    tableHeader.append(tr("Time"));
    tableHeader.append(tr("Operator"));
    tableHeader.append(tr("Param"));
    tableHeader.append(tr("Sample code"));
    tableHeader.append(tr("Material Type"));
    tableHeader.append(tr("Batch No"));
    tableHeader.append(tr("RMS(V)"));
    tableHeader.append(tr("Offset(%)"));
    tableHeader.append(tr("Report"));
    tableHeader.append(tr("Duration"));
    tableHeader.append(tr("Result"));

    ui->tableWidget->clear();
    ui->tableWidget->setColumnCount(tableHeader.count());

    for (int i = 0; i < ui->tableWidget->columnCount(); i++)
    {
        ui->tableWidget->setHorizontalHeaderItem(i, new QTableWidgetItem(tableHeader.at(i)));
    }
}

QString Data::generateTable(QStringList header, QList<ExperimentInfo> info)
{
    QString vrmsStr, offsetStr;

    QString html;
    html += QString("<table width='100%' border='1' style='border-collapse:collapse;' bordercolor='gray'>");

    //tr = table row, th = table header
    html += "<tr style='background-color:gray'>";
    int columnCount = header.count();
    for (int i = 0; i < columnCount; i++) {
        if (header.at(i) != tr("Waveform")) {
            html += QString("<th>%1</th>").arg(header.at(i)) ;
        }
    }
    html += "</tr>";

    //td = table data
    int dataRowCount = info.size();
    for (int i = 0; i < dataRowCount; i++) {
        dataCalc(expList[i], vrmsStr, offsetStr);

        html += "<tr>";

        html += QString("<td>%1</td>").arg(info[i].datetimeExpStart);
        html += QString("<td>%1</td>").arg(info[i].username);
        html += QString("<td>%1</td>").arg(info[i].parameterName);
        html += QString("<td>%1</td>").arg(info[i].sampleName);
        html += QString("<td>%1</td>").arg(info[i].specifications);
        html += QString("<td>%1</td>").arg(info[i].batchNumber);
        html += QString("<td>%1</td>").arg(vrmsStr);
        html += QString("<td>%1</td>").arg(offsetStr);
        html += QString("<td>%1</td>").arg(info[i].duration);
        html += QString("<td>%1</td>").arg(translate(info[i].result));

        html += "</tr>";
    }
    html += "</table>";
    return html;
}

void Data::setReportHtml(int type, const QString html)
{
    if(ReportType::DATA_REPROT == type)
    {
        reportHtml = html;
    }
}

void Data::retranslateUiSlot()
{
    ui->retranslateUi(this);
    retranslateTable();
    if (ui->tableWidget->rowCount() > 0 || ui->tableWidget->showGrid())
    {// 翻译数据表
        showExperimentInfo(expList);
    }

    showAllResultType();
}

void Data::on_btnDateTimeEditStart_clicked()
{
    dateTimePicker->show();
    dateTimePicker->setWhatsThis("data_start_datetimepicker");
    dateTimePicker->setDateTime(ui->dateTimeEditStart->dateTime());
}

void Data::on_btnDateTimeEditEnd_clicked()
{
    dateTimePicker->show();
    dateTimePicker->setWhatsThis("data_end_datetimepicker");
    dateTimePicker->setDateTime(ui->dateTimeEditEnd->dateTime());
}

void Data::setCurrentTimeSlot(int type)
{
    if (TimeSetType::DATA_START == type)
    {
        QDateTime dateTime = QDateTime::currentDateTime();
        QDateTime last30DayDateTime = dateTime.addDays(-30);
        ui->dateTimeEditStart->setDateTime(last30DayDateTime);
        ui->dateTimeEditEnd->setDateTime(dateTime);
    }
}

void Data::changeDateTime(QDateTime dateTime, QString whatsThis)
{
    if (whatsThis == "data_start_datetimepicker") {
        ui->dateTimeEditStart->setDateTime(dateTime);
    } else if (whatsThis == "data_end_datetimepicker") {
        ui->dateTimeEditEnd->setDateTime(dateTime);
    }
}

void Data::viewReportSlot()
{
    bool ok;
    QPushButton * btnViewReport = (QPushButton*)sender();
    int index = btnViewReport->whatsThis().toInt(&ok);
    if (ok && index >= 0 && index < expList.count())
    {
        bdf->showReportPage(expList[index]);
    }
}

void Data::pdfSaveDone(const QString &info, const QString &path)
{
    UserLogger::log(info);

    MsgBox msgBox;
    msgBox.setTitle(tr("DataReport"));
    msgBox.setText(info);
    msgBox.setInformativeText(path);
    msgBox.setBtnCancelVisible(false);
    msgBox.exec();

    ui->btnExport->setEnabled(true);
    Loading::hideLoading();
}
